home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
EnigmA Amiga Run 1999 March
/
EnigmA AMIGA RUN 35 (1999)(G.R. Edizioni)(IT)[!][issue 1999-03].iso
/
earcd
/
utils
/
xad
/
developer
/
sources
/
clients
/
dms.c
next >
Wrap
C/C++ Source or Header
|
1999-01-01
|
45KB
|
1,711 lines
#ifndef XADMASTER_DMS_C
#define XADMASTER_DMS_C
/* Programmheader
Name: DMS.c
Main: xadmaster
Versionstring: $VER: DMS.c 1.4 (04.03.1999)
Author: SDI, Andre R. de la Rocha
Distribution: Freeware
Description: DMS and related disk/file archiver clients
1.0 23.12.98 : first version
1.1 31.01.99 : added unpack stuff
1.2 04.02.99 : bug fixes, first full working version
1.3 16.02.99 : bug fixes
1.4 04.03.99 : added XADFIF_NODATE flag
*/
/* This format seems to have really lots of problems. Append option
does not work correctly, because the crunching algorithm start data
seems to be handled wrong. ENCRYPTION over APPEND borders doe not
work correctly as well. DIZ text sometimes are encrypted, sometimes
are not. Generally all is possible and all may fail. Hopefully there
are not too much archives out there doing such a strange defective
stuff. */
/* This client is lossely based (mainly decrunch stuff) on xDMS
source made by Andre R. de la Rocha. Thanks for your work. The code
has been made reentrant to fit requirements of shared libraries and
also lots of strange files are handled correctly now. Crunch Type
reinitialisation has been fixed as well. This client does not use
DMS header information (except password flag), but always the track
data. This should reduce influence of modified DMS files.
DIZ texts seem to use easy compression (NONE or RLE) always, so they
can be decompressed without decompressiong all the data before.
APPENDED files which use a password, where the normal file does
not use one, will fail. The other way round should work.
*/
/* FMS format:
- pre 2.04 FMS files contain file name in block DMSTRTYPE_FILENAME
- 2.04 format contains additionally information:
LONGWORD protection bits
3 LONGWORDs DateStamp structure
UBYTE size of following text, if bit 7 is set, the text
is a comment
[ UBYTE size of filename, when there was a comment]
*/
#include <proto/xadmaster.h>
#include <proto/exec.h>
#include <exec/memory.h>
#include <dos/dos.h>
#include <dos/doshunks.h>
#include "SDI_compiler.h"
#define SDI_TO_ANSI
#include "SDI_ASM_STD_protos.h"
#ifndef XADMASTERFILE
#define DMS_Client FirstClient
#define NEXTCLIENT 0
UBYTE version[] = "$VER: DMS 1.4 (04.03.1999)";
#endif
#define DMS_VERSION 1
#define DMS_REVISION 4
#define DMSSFX_VERSION DMS_VERSION
#define DMSSFX_REVISION DMS_REVISION
#define SDSSFX_VERSION DMS_VERSION
#define SDSSFX_REVISION DMS_REVISION
/****************************************************************************/
#define DMSINFO_NOZERO (1<<0)
#define DMSINFO_ENCRYPT (1<<1)
#define DMSINFO_APPENDS (1<<2)
#define DMSINFO_BANNER (1<<3)
#define DMSINFO_HIGHDENSITY (1<<4)
#define DMSINFO_PC (1<<5)
#define DMSINFO_DMS_DEVICE_FIX (1<<6)
#define DMSINFO_REGIST_VERSION (1<<7)
#define DMSINFO_DIZ (1<<8)
/* InfoFlags seem to be valid for first part. Appended part may have
other flags! */
#define DMSOSV_AMIGA_AGA (1<<15)
#define DMSCPU_68000 0
#define DMSCPU_68010 1
#define DMSCPU_68020 2
#define DMSCPU_68030 3
#define DMSCPU_68040 4
#define DMSCPU_68060 5
#define DMSCPU_6086 6
#define DMSCPU_8088 7
#define DMSCPU_80188 8
#define DMSCPU_80186 9
#define DMSCPU_80286 10
#define DMSCPU_80386SX 11
#define DMSCPU_80386 12
#define DMSCPU_80486 13
#define DMSCPU_80586 14
#define DMSFPU_NONE 0
#define DMSFPU_68881 1
#define DMSFPU_68882 2
#define DMSFPU_8087 3
#define DMSFPU_80287SX 4
#define DMSFPU_80387 5
#define DMSMACH_UNKNOWN 0
#define DMSMACH_AMIGA 1
#define DMSMACH_PC 2
#define DMSMACH_ATARI 3
#define DMSMACH_MACINTOSH 4
#define DMSTYPE_UNKNOWN 0
#define DMSTYPE_AOS1OFS 1
#define DMSTYPE_AOS1FFS 2
#define DMSTYPE_AOS3INT 3
#define DMSTYPE_AOS3INTFFS 4
#define DMSTYPE_AOS3DIR 5
#define DMSTYPE_AOS3DIRFFS 6
#define DMSTYPE_FMS 7
#define DMSCOMP_NOCOMP 0
#define DMSCOMP_SIMPLE 1
#define DMSCOMP_QUICK 2
#define DMSCOMP_MEDIUM 3
#define DMSCOMP_DEEP 4
#define DMSCOMP_HEAVY1 5
#define DMSCOMP_HEAVY2 6
#define DMSCFLAG_NOINIT (1<<0)
#define DMSCFLAG_HEAVY_C (1<<1)
#define DMSCFLAG_HEAVYRLE (1<<2)
#define DMSCFLAG_HEAVY2 (1<<3) /* own flag */
#define DMSTRTYPE_DIZ 80
#define DMSTRTYPE_BANNER -1
#define DMSTRTYPE_FILENAME 0x03E7
#define DMSTRTYPE_FILESTART 0x03E8
#define DMSPWD_USE 1
#define DMSPWD_NOUSE 2
struct DMSHeader {
ULONG DMSID; /* "DMS!" */
ULONG ID; /* " PRO" or "FILE" */
ULONG InfoFlags; /* DMSINFO_ defines */
ULONG Date; /* UNIX format */
UWORD LowTrack;
UWORD HighTrack;
ULONG PackedSize;
ULONG UnpackedSize;
UWORD OSVersion; /* DMSOSV_ defines */
UWORD OSRevision;
UWORD CPU; /* DMSCPU_ defines */
UWORD FPU; /* DMSFPU_ defines */
UWORD Machine; /* DMSMACH_ defines */
UWORD DiskType2; /* DMSTYPE_ defines */
UWORD CPUSpeed; /* multiplied (in 0.01 MHz) */
ULONG CreationTime;
UWORD CreatorVersion;
UWORD NeededVersion;
UWORD DiskType; /* DMSTYPE_ defines */
UWORD CompMode; /* DMSCOMP_ defines */
UWORD CheckSum;
/* checksums exclude DMSID and checksum word itself */
};
struct DMSTrack {
UWORD TRID; /* "TR" */
WORD TrackNumber;
UWORD pad;
UWORD CMODE_Packed;
UWORD RuntimePacked;
UWORD UnpackedSize;
UBYTE CFlag;
UBYTE CModeTrk; /* DMSCOMP_ defines */
UWORD UncrunchedCRC;
UWORD CrunchedCRC;
UWORD CheckSum;
};
#define DMSNC 510
#define DMSNPT 30
#define DMSN1 510
#define DMSOFFSET 253
#define DMSF 60 /* lookahead buffer size */
#define DMSTHRESHOLD 2
#define DMSN_BYTE (256 - DMSTHRESHOLD + DMSF) /* kinds of characters (character code = 0..DMSN_BYTE-1) */
#define DMST (DMSN_BYTE * 2 - 1) /* size of table */
#define DMSR (DMST - 1) /* position of root */
#define DMSMAX_FREQ 0x8000 /* DMSupdates tree when the */
struct DMSData {
ULONG bitbuf;
STRPTR indata;
UBYTE bitcount;
UBYTE DidInit;
UWORD RTV_Medium;
UBYTE Text[32768];
/* the above are accessed by Medium decruncher and supplied as a short
data structure from SDS SFX */
UWORD UsePwd;
UWORD PassCRC;
UWORD RTV_Pass; /* RunTimeVariable */
UWORD RTV_Quick;
UWORD RTV_Deep;
UWORD RTV_Heavy;
UWORD c_table[4096];
UWORD pt_table[256];
UWORD lastlen;
UWORD np;
UWORD left[2*DMSNC - 1];
UWORD right[2*DMSNC -1 + 9];
UWORD freq[DMST + 1]; /* d->frequency table */
UWORD prnt[DMST + DMSN_BYTE]; /* pointers to parent nodes, except for the */
/* elements [DMST..DMST + DMSN_BYTE - 1] which are used to get */
/* the positions of leaves corresponding to the codes. */
UWORD son[DMST]; /* pointers to child nodes (son[], son[] + 1) */
UBYTE DidInitDEEP;
UBYTE c_len[DMSNC];
UBYTE pt_len[DMSNPT];
};
struct DMSPos {
ULONG startpos; /* decrunch start position */
ULONG firsttrack; /* first decrunch track */
};
/****************************************************************************/
static ULONG DMS_mask_bits[]={
0x000000,0x000001,0x000003,0x000007,0x00000f,0x00001f,
0x00003f,0x00007f,0x0000ff,0x0001ff,0x0003ff,0x0007ff,
0x000fff,0x001fff,0x003fff,0x007fff,0x00ffff,0x01ffff,
0x03ffff,0x07ffff,0x0fffff,0x1fffff,0x3fffff,0x7fffff,
0xffffff};
static UBYTE DMS_d_code[256] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A,
0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B,
0x0C, 0x0C, 0x0C, 0x0C, 0x0D, 0x0D, 0x0D, 0x0D,
0x0E, 0x0E, 0x0E, 0x0E, 0x0F, 0x0F, 0x0F, 0x0F,
0x10, 0x10, 0x10, 0x10, 0x11, 0x11, 0x11, 0x11,
0x12, 0x12, 0x12, 0x12, 0x13, 0x13, 0x13, 0x13,
0x14, 0x14, 0x14, 0x14, 0x15, 0x15, 0x15, 0x15,
0x16, 0x16, 0x16, 0x16, 0x17, 0x17, 0x17, 0x17,
0x18, 0x18, 0x19, 0x19, 0x1A, 0x1A, 0x1B, 0x1B,
0x1C, 0x1C, 0x1D, 0x1D, 0x1E, 0x1E, 0x1F, 0x1F,
0x20, 0x20, 0x21, 0x21, 0x22, 0x22, 0x23, 0x23,
0x24, 0x24, 0x25, 0x25, 0x26, 0x26, 0x27, 0x27,
0x28, 0x28, 0x29, 0x29, 0x2A, 0x2A, 0x2B, 0x2B,
0x2C, 0x2C, 0x2D, 0x2D, 0x2E, 0x2E, 0x2F, 0x2F,
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
};
static UBYTE DMS_d_len[256] = {
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
};
/****************************************************************************/
static LONG DMSUnpRLE(STRPTR *res, ULONG size, struct ExecBase *SysBase)
{
STRPTR out, outstore, outend, in = *res;
UWORD n;
UBYTE a,b;
LONG err = 0;
if(!(out = outstore = (STRPTR) AllocVec(size+1, MEMF_PUBLIC|MEMF_CLEAR)))
return XADERR_NOMEMORY;
outend = out+size;
while(out < outend && !err)
{
if((a = *(in++)) != 0x90)
*(out++) = a;
else if(!(b = *(in++)))
*(out++) = a;
else
{
a = *(in++);
if(b == 0xFF)
{
n = *(in++);
n = ((n<<8) + *(in++));
}
else
n = b;
if(out+n > outend)
err = XADERR_ILLEGALDATA;
else
{
memset(out,a,n);
out += n;
}
}
}
FreeVec(*res);
*res = outstore;
return err;
}
/****************************************************************************/
#define DMSGETBITS(n) ((UWORD)(d->bitbuf >> (d->bitcount-(n))))
#define DMSDROPBITS(n) {d->bitbuf &= DMS_mask_bits[d->bitcount-=(n)]; \
while (d->bitcount<16) {d->bitbuf = (d->bitbuf << 8) | \
*d->indata++; d->bitcount += 8;}}
static void DMSinitbitbuf(STRPTR in, struct DMSData *d)
{
d->bitbuf = 0;
d->bitcount = 0;
d->indata = in;
DMSDROPBITS(0);
}
static LONG DMSUnpQUICK(STRPTR *res, ULONG size, struct DMSData *d, struct ExecBase *SysBase)
{
STRPTR out, outstore, outend, in = *res;
UWORD i,j;
LONG err = 0;
if(!(out = outstore = (STRPTR) AllocVec(size+1, MEMF_PUBLIC|MEMF_CLEAR)))
return XADERR_NOMEMORY;
d->DidInit = 0; /* clear Init flag */
DMSinitbitbuf(in, d);
outend = out + size;
while (out < outend)
{
if(DMSGETBITS(1))
{
DMSDROPBITS(1);
*out++ = d->Text[d->RTV_Quick++ & 0xFF] = (UBYTE) DMSGETBITS(8);
DMSDROPBITS(8);
}
else
{
DMSDROPBITS(1);
j = DMSGETBITS(2)+2;
DMSDROPBITS(2);
i = d->RTV_Quick - DMSGETBITS(8) - 1;
DMSDROPBITS(8);
if(j + out > outend)
err = XADERR_ILLEGALDATA;
else
while(j--)
*out++ = d->Text[d->RTV_Quick++ & 0xFF] = d->Text[i++ & 0xFF];
}
}
d->RTV_Quick = (d->RTV_Quick+5) & 0xFF;
FreeVec(*res);
*res = outstore;
return err;
}
/****************************************************************************/
static LONG DMSUnpMEDIUM(STRPTR *res, ULONG size, struct DMSData *d, struct ExecBase *SysBase)
{
STRPTR out, outstore, outend, in = *res;
UWORD i,j, c;
LONG err = 0;
UBYTE u;
if(!(out = outstore = (STRPTR) AllocVec(size+1, MEMF_PUBLIC|MEMF_CLEAR)))
return XADERR_NOMEMORY;
d->DidInit = 0; /* clear Init flag */
DMSinitbitbuf(in, d);
outend = out + size;
while(out < outend)
{
if(DMSGETBITS(1))
{
DMSDROPBITS(1);
*out++ = d->Text[d->RTV_Medium++ & 0x3FFF] = (UBYTE)DMSGETBITS(8);
DMSDROPBITS(8);
}
else
{
DMSDROPBITS(1);
c = DMSGETBITS(8);
DMSDROPBITS(8);
j = (UWORD) (DMS_d_code[c]+3);
u = DMS_d_len[c];
c = (UWORD) (((c << u) | DMSGETBITS(u)) & 0xff);
DMSDROPBITS(u);
u = DMS_d_len[c];
c = (UWORD) ((DMS_d_code[c] << 8) | (((c << u) | DMSGETBITS(u)) & 0xff));
DMSDROPBITS(u);
i = (UWORD) (d->RTV_Medium - c - 1);
if(j + out > outend)
err = XADERR_ILLEGALDATA;
else
while(j--)
*out++ = d->Text[d->RTV_Medium++ & 0x3FFF] = d->Text[i++ & 0x3FFF];
}
}
d->RTV_Medium = (UWORD)((d->RTV_Medium+66) & 0x3FFF);
FreeVec(*res);
*res = outstore;
return err;
}
/****************************************************************************/
/* reconstruction of tree */
static void DMSreconst(struct DMSData *d)
{
UWORD i, j, k, f, l;
/* collect leaf nodes in the first half of the table */
/* and replace the d->freq by (d->freq + 1) / 2. */
j = 0;
for (i = 0; i < DMST; i++)
{
if(d->son[i] >= DMST)
{
d->freq[j] = (UWORD) ((d->freq[i] + 1) / 2);
d->son[j] = d->son[i];
j++;
}
}
/* begin constructing tree by connecting d->sons */
for(i = 0, j = DMSN_BYTE; j < DMST; i += 2, j++)
{
k = (UWORD) (i + 1);
f = d->freq[j] = (UWORD) (d->freq[i] + d->freq[k]);
for(k = (UWORD)(j - 1); f < d->freq[k]; k--)
;
k++;
for(l = j; l > k; --l)
{
d->freq[l] = d->freq[l-1];
d->son[l] = d->son[l-1];
}
d->freq[k] = f;
d->son[k] = i;
}
/* connect d->prnt */
for(i = 0; i < DMST; i++)
{
if((k = d->son[i]) >= DMST)
d->prnt[k] = i;
else
d->prnt[k] = d->prnt[k + 1] = i;
}
}
/* increment d->frequency of given code by one, and update tree */
static void DMSupdate(UWORD c, struct DMSData *d)
{
UWORD i, j, k, l;
if(d->freq[DMSR] == DMSMAX_FREQ)
DMSreconst(d);
c = d->prnt[c + DMST];
do
{
k = ++d->freq[c];
/* if the order is disturbed, exchange nodes */
if(k > d->freq[l = (UWORD)(c + 1)])
{
while(k > d->freq[++l])
;
l--;
d->freq[c] = d->freq[l];
d->freq[l] = k;
i = d->son[c];
d->prnt[i] = l;
if(i < DMST)
d->prnt[i + 1] = l;
j = d->son[l];
d->son[l] = i;
d->prnt[j] = c;
if(j < DMST)
d->prnt[j + 1] = c;
d->son[c] = j;
c = l;
}
} while((c = d->prnt[c]) != 0); /* repeat up to root */
}
static UWORD DMSDecodeChar(struct DMSData *d)
{
UWORD c;
c = d->son[DMSR];
/* travel from root to leaf, */
/* choosing the smaller child node (d->son[]) if the read bit is 0, */
/* the bigger (d->son[]+1) if 1 */
while(c < DMST)
{
c = d->son[c + DMSGETBITS(1)];
DMSDROPBITS(1);
}
c -= DMST;
DMSupdate(c, d);
return c;
}
static UWORD DMSDecodePosition(struct DMSData *d)
{
UWORD i, j, c;
i = DMSGETBITS(8);
DMSDROPBITS(8);
c = (UWORD) (DMS_d_code[i] << 8);
j = DMS_d_len[i];
i = (UWORD) (((i << j) | DMSGETBITS(j)) & 0xff);
DMSDROPBITS(j);
return (UWORD) (c | i);
}
static LONG DMSUnpDEEP(STRPTR *res, ULONG size, struct DMSData *d, struct ExecBase *SysBase)
{
STRPTR out, outstore, outend, in = *res;
UWORD i,j, c;
LONG err = 0;
if(!(out = outstore = (STRPTR) AllocVec(size+1, MEMF_PUBLIC|MEMF_CLEAR)))
return XADERR_NOMEMORY;
d->DidInitDEEP = d->DidInit = 0; /* clear Init flag */
DMSinitbitbuf(in, d);
outend = out + size;
while(out < outend)
{
c = DMSDecodeChar(d);
if(c < 256)
*out++ = d->Text[d->RTV_Deep++ & 0x3FFF] = (UBYTE)c;
else
{
j = (UWORD) (c - 255 + DMSTHRESHOLD);
i = (UWORD) (d->RTV_Deep - DMSDecodePosition(d) - 1);
if(j + out > outend)
err = XADERR_ILLEGALDATA;
else
while (j--)
*out++ = d->Text[d->RTV_Deep++ & 0x3FFF] = d->Text[i++ & 0x3FFF];
}
}
d->RTV_Deep = (UWORD)((d->RTV_Deep+60) & 0x3FFF);
FreeVec(*res);
*res = outstore;
return err;
}
/****************************************************************************/
struct DMSTableData {
WORD c;
UWORD n;
UWORD tblsiz;
UWORD len;
UWORD depth;
UWORD maxdepth;
UWORD avail;
UWORD codeword;
UWORD bit;
UWORD * tbl;
UWORD TabErr;
STRPTR blen;
UWORD * left; /* copy of data in DMSData */
UWORD * right; /* copy of data in DMSData */
};
static UWORD DMSmktbl(struct DMSTableData *t)
{
UWORD i=0;
if(t->TabErr)
return 0;
if(t->len == t->depth)
{
while(++t->c < t->n)
if(t->blen[t->c] == t->len)
{
i = t->codeword;
t->codeword += t->bit;
if(t->codeword > t->tblsiz)
{
t->TabErr=1;
return 0;
}
while(i < t->codeword)
t->tbl[i++] = (UWORD) t->c;
return (UWORD) t->c;
}
t->c = -1;
t->len++;
t->bit >>= 1;
}
t->depth++;
if(t->depth < t->maxdepth)
{
(void) DMSmktbl(t);
(void) DMSmktbl(t);
}
else if(t->depth > 32)
{
t->TabErr = 2;
return 0;
}
else
{
if((i = t->avail++) >= 2 * t->n - 1)
{
t->TabErr = 3;
return 0;
}
t->left[i] = DMSmktbl(t);
t->right[i] = DMSmktbl(t);
if(t->codeword >= t->tblsiz)
{
t->TabErr = 4;
return 0;
}
if(t->depth == t->maxdepth)
t->tbl[t->codeword++] = i;
}
t->depth--;
return i;
}
static UWORD DMSmake_table(UWORD nchar, UBYTE bitlen[], UWORD tablebits, UWORD table[],
struct DMSData *d)
{
struct DMSTableData t;
t.left = d->left;
t.right = d->right;
t.n = t.avail = nchar;
t.blen = bitlen;
t.tbl = table;
t.tblsiz = (UWORD) (1 << tablebits);
t.bit = (UWORD) (t.tblsiz / 2);
t.maxdepth = (UWORD)(tablebits + 1);
t.depth = t.len = 1;
t.c = -1;
t.codeword = 0;
t.TabErr = 0;
(void) DMSmktbl(&t); /* left subtree */
(void) DMSmktbl(&t); /* right subtree */
if(t.TabErr)
return t.TabErr;
if(t.codeword != t.tblsiz)
return 5;
return 0;
}
static UWORD DMSdecode_c(struct DMSData *d)
{
UWORD i, j, m;
j = d->c_table[DMSGETBITS(12)];
if(j < DMSN1)
{
DMSDROPBITS(d->c_len[j]);
}
else
{
DMSDROPBITS(12);
i = DMSGETBITS(16);
m = 0x8000;
do
{
if(i & m)
j = d->right[j];
else
j = d->left[j];
m >>= 1;
} while (j >= DMSN1);
DMSDROPBITS(d->c_len[j] - 12);
}
return j;
}
static UWORD DMSdecode_p(struct DMSData *d)
{
UWORD i, j, m;
j = d->pt_table[DMSGETBITS(8)];
if(j < d->np)
{
DMSDROPBITS(d->pt_len[j]);
}
else
{
DMSDROPBITS(8);
i = DMSGETBITS(16);
m = 0x8000;
do
{
if(i & m)
j = d->right[j];
else
j = d->left[j];
m >>= 1;
} while (j >= d->np);
DMSDROPBITS(d->pt_len[j] - 8);
}
if(j != d->np-1)
{
if(j > 0)
{
j = (UWORD)(DMSGETBITS(i=(UWORD)(j-1)) | (1 << (j-1)));
DMSDROPBITS(i);
}
d->lastlen=j;
}
return d->lastlen;
}
static UWORD DMSread_tree_c(struct DMSData *d)
{
UWORD i,n;
n = DMSGETBITS(9);
DMSDROPBITS(9);
if(n > 0)
{
for(i=0; i<n; i++)
{
d->c_len[i] = (UBYTE)DMSGETBITS(5);
DMSDROPBITS(5);
}
for(i=n; i<510; i++)
d->c_len[i] = 0;
if(DMSmake_table(510,d->c_len,12,d->c_table, d))
return 1;
}
else
{
n = DMSGETBITS(9);
DMSDROPBITS(9);
for(i=0; i<510; i++)
d->c_len[i] = 0;
for(i=0; i<4096; i++)
d->c_table[i] = n;
}
return 0;
}
static UWORD DMSread_tree_p(struct DMSData *d)
{
UWORD i,n;
n = DMSGETBITS(5);
DMSDROPBITS(5);
if(n > 0)
{
for(i=0; i<n; i++)
{
d->pt_len[i] = (UBYTE) DMSGETBITS(4);
DMSDROPBITS(4);
}
for(i=n; i<d->np; i++)
d->pt_len[i] = 0;
if(DMSmake_table(d->np,d->pt_len,8,d->pt_table, d))
return 1;
}
else
{
n = DMSGETBITS(5);
DMSDROPBITS(5);
for(i=0; i<d->np; i++)
d->pt_len[i] = 0;
for (i=0; i<256; i++)
d->pt_table[i] = n;
}
return 0;
}
static LONG DMSUnpHEAVY(STRPTR *res, ULONG size, UBYTE flags, struct DMSData *d, struct ExecBase *SysBase)
{
STRPTR out, outstore, outend, in = *res;
UWORD i,j, c, bitmask;
LONG err = 0;
if(!(out = outstore = (STRPTR) AllocVec(size+1, MEMF_PUBLIC|MEMF_CLEAR)))
return XADERR_NOMEMORY;
d->DidInit = 0; /* clear Init flag */
/* Heavy 1 uses a 4Kb dictionary, Heavy 2 uses 8Kb */
if(flags & DMSCFLAG_HEAVY2)
{
d->np = 15;
bitmask = 0x1fff;
}
else
{
d->np = 14;
bitmask = 0x0fff;
}
DMSinitbitbuf(in, d);
outend = out + size;
if(flags & DMSCFLAG_HEAVY_C)
{
if(DMSread_tree_c(d))
return 1;
if(DMSread_tree_p(d))
return 2;
}
while(out < outend)
{
c = DMSdecode_c(d);
if(c < 256)
*out++ = d->Text[d->RTV_Heavy++ & bitmask] = (UBYTE)c;
else
{
j = (UWORD) (c - DMSOFFSET);
i = (UWORD) (d->RTV_Heavy - DMSdecode_p(d) - 1);
if(j + out > outend)
err = XADERR_ILLEGALDATA;
else
while(j--)
*out++ = d->Text[d->RTV_Heavy++ & bitmask] = d->Text[i++ & bitmask];
}
}
FreeVec(*res);
*res = outstore;
return err;
}
/****************************************************************************/
/* track 80 is FILEID.DIZ, track 0xffff (-1) is Banner */
/* and track 0 with 1024 bytes only is a fake boot block with more advertising */
static LONG testDMSTrack(struct DMSTrack *t, struct xadMasterBase *xadMasterBase)
{
if(t->TRID != 0x5452)
return XADERR_ILLEGALDATA;
if(xadCalcCRC16(XADCRC16_ID1, 0, sizeof(struct DMSTrack)-2,
(STRPTR)t) != t->CheckSum)
return XADERR_CHECKSUM;
return 0;
}
static UWORD CheckSumDMS(STRPTR mem, ULONG size)
{
UWORD u = 0;
while(size--)
u += *mem++;
return u;
}
static void DecryptDMS(STRPTR p, ULONG size, struct DMSData *d)
{
UWORD t;
while(size--)
{
t = (UWORD) *p;
*p++ ^= (UBYTE) d->RTV_Pass;
d->RTV_Pass = (UWORD)((d->RTV_Pass >> 1) + t);
}
}
static void DMSInitData(struct DMSData *d)
{
d->RTV_Quick = 251;
d->RTV_Medium = 0x3FBE;
d->RTV_Deep = 0x3fc4;
if(!d->DidInitDEEP)
{
UWORD i, j;
for(i = 0; i < DMSN_BYTE; i++)
{
d->freq[i] = 1;
d->son[i] = (UWORD)(i + DMST);
d->prnt[i + DMST] = i;
}
i = 0;
j = DMSN_BYTE;
while(j <= DMSR)
{
d->freq[j] = (UWORD) (d->freq[i] + d->freq[i + 1]);
d->son[j] = i;
d->prnt[i] = d->prnt[i + 1] = j;
i += 2;
j++;
}
d->freq[DMST] = 0xffff;
d->prnt[DMSR] = 0;
}
d->DidInit = d->DidInitDEEP = 1;
memset(d->Text,0,0x3fc8);
}
/* always make buffer 1 byte larger, which is filled with 0! */
static LONG DecrunchDMS(struct DMSTrack *t, struct xadArchiveInfo *ai,
struct xadMasterBase *xadMasterBase, STRPTR *res, struct DMSData *d)
{
APTR inbuf;
LONG err;
struct ExecBase * SysBase = xadMasterBase->xmb_SysBase;
*res = 0;
if(!(inbuf = AllocVec(t->CMODE_Packed+1, MEMF_PUBLIC|MEMF_CLEAR)))
return XADERR_NOMEMORY;
if((err = xadHookAccess(XADAC_READ, t->CMODE_Packed, inbuf, ai)))
{
FreeVec(inbuf);
return err;
}
*res = inbuf;
if(d->UsePwd == DMSPWD_USE && d->PassCRC)
DecryptDMS(inbuf, t->CMODE_Packed, d);
switch(t->CModeTrk)
{
case DMSCOMP_NOCOMP: break;
case DMSCOMP_SIMPLE: err = DMSUnpRLE(res, t->UnpackedSize, SysBase); break;
case DMSCOMP_QUICK:
if(!(err = DMSUnpQUICK(res, t->RuntimePacked, d, SysBase)))
err = DMSUnpRLE(res, t->UnpackedSize, SysBase);
break;
case DMSCOMP_MEDIUM:
if(!(err = DMSUnpMEDIUM(res, t->RuntimePacked, d, SysBase)))
err = DMSUnpRLE(res, t->UnpackedSize, SysBase);
break;
case DMSCOMP_DEEP:
if(!(err = DMSUnpDEEP(res, t->RuntimePacked, d, SysBase)))
err = DMSUnpRLE(res, t->UnpackedSize, SysBase);
break;
case DMSCOMP_HEAVY1: case DMSCOMP_HEAVY2:
if(t->CModeTrk == DMSCOMP_HEAVY1)
err = DMSUnpHEAVY(res, t->RuntimePacked, t->CFlag & ~DMSCFLAG_HEAVY2, d, SysBase);
else
err = DMSUnpHEAVY(res, t->RuntimePacked, t->CFlag | DMSCFLAG_HEAVY2, d, SysBase);
if(t->CFlag & DMSCFLAG_HEAVYRLE && !err)
err = DMSUnpRLE(res, t->UnpackedSize, SysBase);
break;
default: err = XADERR_DECRUNCH; break;
}
if(!err && CheckSumDMS(*res, t->UnpackedSize) != t->UncrunchedCRC)
{
/* try again without password */
if(d->UsePwd == DMSPWD_USE && d->PassCRC && !(err = xadHookAccess(XADAC_INPUTSEEK,
-t->CMODE_Packed, 0, ai)))
{
FreeVec(*res);
d->UsePwd = DMSPWD_NOUSE;
return DecrunchDMS(t, ai, xadMasterBase, res, d);
}
if(!err)
err = d->UsePwd ? XADERR_PASSWORD : XADERR_CHECKSUM;
}
if(!(t->CFlag & DMSCFLAG_NOINIT) && !(d->DidInit))
DMSInitData(d);
if(err)
{
if(*res)
{
FreeVec(*res);
*res= 0;
}
}
return err;
}
static struct DMSData *GetDMSData(struct xadMasterBase *xadMasterBase, STRPTR pwd)
{
struct ExecBase * SysBase = xadMasterBase->xmb_SysBase;
struct DMSData *d;
if((d = (struct DMSData *) AllocVec(sizeof(struct DMSData), MEMF_CLEAR)))
{
DMSInitData(d);
if(pwd)
d->RTV_Pass = d->PassCRC = xadCalcCRC16(XADCRC16_ID1, 0, strlen(pwd), pwd);
}
return d;
}
/****************************************************************************/
ASM(BOOL) DMS_RecogData(REG(d0, ULONG size), REG(a0, struct DMSHeader *h),
REG(a6, struct xadMasterBase *xadMasterBase))
{
if(h->DMSID == 0x444D5321 && xadCalcCRC16(XADCRC16_ID1, 0,
sizeof(struct DMSHeader)-6, ((STRPTR)h)+4) == h->CheckSum)
return 1;
else
return 0;
}
/****************************************************************************/
/* Only the crypted information is used form DMS header. All the other
information is taken from data directly, to allow these lots of
modified headers. */
static struct xadDiskInfo *DMSOneArc(struct xadMasterBase *xadMasterBase,
struct xadArchiveInfo *ai, LONG *more, LONG crypted, LONG *ret)
{
struct ExecBase * SysBase = xadMasterBase->xmb_SysBase;
struct xadDiskInfo *di;
struct xadTextInfo *ti = 0, *ti2;
struct DMSData *d;
struct DMSTrack t;
LONG err = 0, stop = 0, tracksize = 0;
LONG lowcyl = -1, highcyl = -1;
STRPTR zerotxt = 0;
ULONG zerosize = 0;
*more = 0;
if((di = (struct xadDiskInfo *) xadAllocObject(XADOBJ_DISKINFO,
XAD_OBJPRIVINFOSIZE, sizeof(struct DMSPos), TAG_DONE)))
{
struct DMSPos *dpos;
dpos = (struct DMSPos *) (di->xdi_PrivateInfo);
if((d = GetDMSData(xadMasterBase, ai->xai_Password)))
{
if(crypted)
d->UsePwd = DMSPWD_USE;
dpos->startpos = ai->xai_InPos;
while(!stop && !err)
{
if(xadHookAccess(XADAC_READ, sizeof(struct DMSTrack), &t, ai))
stop = 1;
else
{
if(testDMSTrack(&t, xadMasterBase))
stop = 2; /* stop > 1 means seek back one Track */
else
{
if(zerotxt)
{
while(zerosize && !zerotxt[zerosize-1])
--zerosize;
if(t.TrackNumber != 1 && zerosize && zerosize <= 2048) /* was a information text */
{
highcyl = lowcyl = -1; /* reset these two */
if((ti2 = (struct xadTextInfo *) xadAllocObjectA(XADOBJ_TEXTINFO, 0)))
{
if(ti)
ti->xti_Next = ti2;
else
di->xdi_TextInfo = ti2;
ti = ti2;
if(!(ti2->xti_Text = (STRPTR) AllocVec(zerosize+1, MEMF_PUBLIC|MEMF_CLEAR)))
err = XADERR_NOMEMORY;
else
{
ti2->xti_Size = zerosize;
CopyMem(zerotxt, ti->xti_Text, zerosize);
}
}
else
err = XADERR_NOMEMORY;
}
FreeVec(zerotxt);
zerotxt = 0;
}
/* Normally only -1 is allowed as banner, but I found at least
one file using -2. */
if(t.TrackNumber < 0 || t.TrackNumber == DMSTRTYPE_DIZ ||
(!t.TrackNumber && t.UnpackedSize == 1024))
{
if((ti2 = (struct xadTextInfo *) xadAllocObjectA(XADOBJ_TEXTINFO, 0)))
{
if(t.TrackNumber == DMSTRTYPE_DIZ)
ti2->xti_Flags |= XADTIF_FILEDIZ;
if(!DecrunchDMS(&t, ai, xadMasterBase, &ti2->xti_Text, d))
ti2->xti_Size = t.UnpackedSize;
else if(crypted && !d->PassCRC)
ti2->xti_Flags |= XADTIF_CRYPTED;
if(ti)
ti->xti_Next = ti2;
else
di->xdi_TextInfo = ti2;
ti = ti2;
}
else
err = XADERR_NOMEMORY;
}
else
{
if(highcyl == -1)
{
highcyl = lowcyl = t.TrackNumber;
tracksize = t.UnpackedSize;
dpos->firsttrack = ai->xai_InPos-sizeof(struct DMSTrack);
if(!t.TrackNumber)
{
zerosize = t.UnpackedSize;
if((DecrunchDMS(&t, ai, xadMasterBase, &zerotxt, d)))
zerotxt = 0; /* ignore it */
continue;
}
}
else if(t.TrackNumber != highcyl+1 || tracksize != t.UnpackedSize)
{
stop = 3; break;
}
else
++highcyl;
if(d->UsePwd)
{
STRPTR a;
if(!(a = AllocMem(t.CMODE_Packed, MEMF_ANY)))
err = XADERR_NOMEMORY;
else
{
if(!(err = xadHookAccess(XADAC_READ, t.CMODE_Packed, a, ai)))
DecryptDMS(a, t.CMODE_Packed, d); /* to get a valid pwd pointer */
FreeMem(a, t.CMODE_Packed);
}
}
else
err = xadHookAccess(XADAC_INPUTSEEK, t.CMODE_Packed, 0, ai);
}
} /* testDMSTrack */
} /* xadHookAccess */
} /* while */
if(zerotxt) /* in case there is only one zero track and nothing else */
{
FreeVec(zerotxt);
zerotxt = 0;
}
if(stop > 1)
err = xadHookAccess(XADAC_INPUTSEEK, -sizeof(struct DMSTrack), &t, ai);
if(!tracksize || lowcyl == -1 || highcyl == -1 || tracksize % (2*512))
err = XADERR_ILLEGALDATA;
else
{
if(crypted & DMSINFO_ENCRYPT)
di->xdi_Flags = XADDIF_CRYPTED;
tracksize /= (2*512);
di->xdi_LowCyl = lowcyl;
di->xdi_HighCyl = highcyl;
di->xdi_SectorSize = 512;
di->xdi_Heads = 2;
di->xdi_Cylinders = 80;
switch(tracksize)
{
case 18: case 9:
di->xdi_EntryInfo = "MSDOS disk"; /* no break! */
case 22: case 11:
di->xdi_TrackSectors = tracksize;
break;
default: err = XADERR_ILLEGALDATA; break;
}
di->xdi_CylSectors = 2 * di->xdi_TrackSectors;
di->xdi_TotalSectors = 80 * di->xdi_CylSectors;
}
FreeVec(d);
} /* GetDMSData */
else
err = XADERR_NOMEMORY;
if(err)
{
for(ti = di->xdi_TextInfo; ti; ti = ti2)
{
ti2 = ti->xti_Next;
if(ti->xti_Text)
FreeVec(ti->xti_Text);
xadFreeObjectA(ti, 0);
}
xadFreeObjectA(di, 0);
di = 0;
}
} /* xadAllocObjectA */
else
err = XADERR_NOMEMORY;
*ret = err;
if(stop == 3 && !err)
*more = 1;
return di;
}
ASM(LONG) DMS_GetInfo(REG(a0, struct xadArchiveInfo *ai),
REG(a6, struct xadMasterBase *xadMasterBase))
{
struct ExecBase * SysBase = xadMasterBase->xmb_SysBase;
LONG err = 0;
struct DMSHeader h;
struct DMSTrack t = {0};
struct xadFileInfo *fi = 0, *fi2;
struct xadDiskInfo *di = 0, *di2;
ULONG num = 1, i, j;
/* appended stuff is treated as own archive, as there may be gaps and double
parts due to the chaotic file format of DMS. */
while(!err && !xadHookAccess(XADAC_READ, sizeof(struct DMSHeader), &h, ai))
{
if(!testDMSTrack((struct DMSTrack *) &h, xadMasterBase))
err = xadHookAccess(XADAC_INPUTSEEK, sizeof(struct DMSTrack)+
sizeof(struct DMSHeader)+((struct DMSTrack *)&h)->CMODE_Packed, 0, ai);
else
{
if(!DMS_RecogData(sizeof(struct DMSHeader), &h, xadMasterBase))
return 0;
if(h.InfoFlags & DMSINFO_ENCRYPT)
ai->xai_Flags |= XADAIF_CRYPTED;
if(h.DiskType2 == DMSTYPE_FMS || h.DiskType == DMSTYPE_FMS)
{
if(!(err = xadHookAccess(XADAC_READ, sizeof(struct DMSTrack), &t, ai)) &&
!(err = testDMSTrack(&t, xadMasterBase)) && t.TrackNumber == DMSTRTYPE_FILENAME)
{
if(!(fi2 = (struct xadFileInfo *) xadAllocObject(XADOBJ_FILEINFO,
XAD_OBJNAMESIZE, t.UnpackedSize+1, TAG_DONE)))
return XADERR_NOMEMORY;
if(!(err = xadHookAccess(XADAC_READ, t.UnpackedSize, fi2->xfi_FileName, ai)))
{
i = ai->xai_InPos;
j = 0;
while(j < h.UnpackedSize && !err)
{
if(!(err = xadHookAccess(XADAC_READ, sizeof(struct DMSTrack), &t, ai)) &&
!(err = testDMSTrack(&t, xadMasterBase)))
{
if(!(err = xadHookAccess(XADAC_INPUTSEEK, t.CMODE_Packed, 0, ai)))
j += t.UnpackedSize;
}
}
if(!err)
{
if(h.InfoFlags & DMSINFO_ENCRYPT)
fi2->xfi_Flags = XADFIF_CRYPTED;
h.Date -= 7*60*60;
if(!fi2->xfi_FileName[0]) /* This is a 2.04 FMS files */
{
struct FMSInfo {
LONG prot;
struct DateStamp d;
} inf;
CopyMem(fi2->xfi_FileName, &inf, sizeof(struct FMSInfo));
fi2->xfi_FileName += sizeof(struct FMSInfo);
fi2->xfi_Protection = inf.prot;
err = xadConvertDates(XAD_DATEDATESTAMP, &inf.d,
XAD_GETDATEXADDATE, &fi2->xfi_Date, TAG_DONE);
if(fi2->xfi_FileName[0] & 0x80)
{
fi2->xfi_Comment = fi2->xfi_FileName+1;
fi2->xfi_FileName += (fi2->xfi_FileName[0]&0x7F)+1;
}
*(fi2->xfi_FileName++) = 0; /* clear size (make C pointer) */
}
else
err = xadConvertDates(XAD_DATEUNIX, h.Date,
XAD_GETDATEXADDATE, &fi2->xfi_Date, XAD_MAKELOCALDATE, 1, TAG_DONE);
fi2->xfi_PrivateInfo = (APTR) i;
fi2->xfi_EntryNumber = num++;
fi2->xfi_Size = h.UnpackedSize;
fi2->xfi_CrunchSize = h.PackedSize;
if(fi)
fi->xfi_Next = fi2;
else
ai->xai_FileInfo = fi2;
fi = fi2;
fi2 = 0;
}
}
if(fi2)
xadFreeObjectA(fi2, 0);
}
}
else /* is a disk archive */
{
LONG more = 1;
while(more)
{
if((di2 = DMSOneArc(xadMasterBase, ai, &more, h.InfoFlags & DMSINFO_ENCRYPT, &err)))
{
di2->xdi_EntryNumber = num++;
if(di)
di->xdi_Next = di2;
else
ai->xai_DiskInfo = di2;
di = di2;
}
}
} /* DISK ARCHIVE */
} /* found correct track */
if(err)
ai->xai_Flags |= XADAIF_FILECORRUPT;
} /* while */
return 0;
}
/****************************************************************************/
ASM(LONG) DMS_UnArchive(REG(a0, struct xadArchiveInfo *ai),
REG(a6, struct xadMasterBase *xadMasterBase))
{
struct ExecBase * SysBase = xadMasterBase->xmb_SysBase;
struct DMSTrack t;
LONG i;
LONG err = 0;
STRPTR pwd = ai->xai_Password;
struct DMSData *d;
if((ai->xai_CurFile && !(ai->xai_CurFile->xfi_Flags & XADFIF_CRYPTED)) ||
!(ai->xai_CurDisk->xdi_Flags & XADDIF_CRYPTED))
pwd = 0;
else if(!pwd)
return XADERR_PASSWORD;
if(!(d = GetDMSData(xadMasterBase, pwd)))
return XADERR_NOMEMORY;
if(ai->xai_CurFile)
{
struct xadFileInfo *fi;
fi = ai->xai_CurFile;
if(fi->xfi_Flags & XADFIF_CRYPTED)
d->UsePwd = DMSPWD_USE;
if(ai->xai_InPos != (ULONG) fi->xfi_PrivateInfo)
err = xadHookAccess(XADAC_INPUTSEEK, ((ULONG) fi->xfi_PrivateInfo) - ai->xai_InPos, 0, ai);
for(i = DMSTRTYPE_FILESTART; !err && ai->xai_OutSize < fi->xfi_Size; ++i)
{
if(!(err = xadHookAccess(XADAC_READ, sizeof(struct DMSTrack), &t, ai)) &&
!(err = testDMSTrack(&t, xadMasterBase)))
{
STRPTR res;
if(i != t.TrackNumber)
err = XADERR_ILLEGALDATA;
else if(!(err = DecrunchDMS(&t, ai, xadMasterBase, &res, d)))
{
err = xadHookAccess(XADAC_WRITE, t.UnpackedSize, res, ai);
FreeVec(res);
}
}
}
}
else
{
struct xadDiskInfo *di;
struct DMSPos *dpos;
di = ai->xai_CurDisk;
dpos = (struct DMSPos *) (di->xdi_PrivateInfo);
if(di->xdi_Flags & XADDIF_CRYPTED)
d->UsePwd = DMSPWD_USE;
if(ai->xai_InPos != dpos->startpos)
err = xadHookAccess(XADAC_INPUTSEEK, dpos->startpos - ai->xai_InPos, 0, ai);
for(i = ai->xai_LowCyl; !err && i <= ai->xai_HighCyl;)
{
if(!(err = xadHookAccess(XADAC_READ, sizeof(struct DMSTrack), &t, ai)) &&
!(err = testDMSTrack(&t, xadMasterBase)))
{
STRPTR res;
if(!(err = DecrunchDMS(&t, ai, xadMasterBase, &res, d)))
{
if(ai->xai_InPos > dpos->firsttrack) /* skip unusable parts */
{
if(i == t.TrackNumber)
{
err = xadHookAccess(XADAC_WRITE, t.UnpackedSize, res, ai); ++i;
}
else if(t.TrackNumber > i)
err = XADERR_ILLEGALDATA;
}
FreeVec(res);
}
}
}
}
FreeVec(d);
return err;
}
/****************************************************************************/
ASM(void) DMS_Free(REG(a0, struct xadArchiveInfo *ai),
REG(a6, struct xadMasterBase *xadMasterBase))
{
struct ExecBase * SysBase = xadMasterBase->xmb_SysBase;
struct xadFileInfo *fi, *fi2;
struct xadDiskInfo *di, *di2;
struct xadTextInfo *ti, *ti2;
for(fi = ai->xai_FileInfo; fi; fi = fi2)
{
fi2 = fi->xfi_Next;
xadFreeObjectA(fi, 0);
}
ai->xai_FileInfo = 0;
for(di = ai->xai_DiskInfo; di; di = di2)
{
di2 = di->xdi_Next;
for(ti = di->xdi_TextInfo; ti; ti = ti2)
{
ti2 = ti->xti_Next;
if(ti->xti_Text)
FreeVec(ti->xti_Text);
xadFreeObjectA(ti, 0);
}
xadFreeObjectA(di, 0);
}
ai->xai_DiskInfo = 0;
}
/****************************************************************************/
ASM(BOOL) DMSSFX_RecogData(REG(d0, ULONG size), REG(a0, ULONG *data),
REG(a6, struct xadMasterBase *xadMasterBase))
{
if(*data == HUNK_HEADER)
{
if(data[5] == 0x1605 && data[6] == 0x1C24 && data[16] == 0x303C05CD &&
data[17] == 0x421B51C8 && data[18] == 0xFFFC47F9)
return 1;
if(data[10] == 0x24E2 && data[9] == 0x60000006 && data[11] == 0x48E77EFE &&
data[12] == 0x24482400 && data[16] == 0x3B61425B)
return 1; /* defective 2.04 SFX arcs */
}
return 0;
}
/****************************************************************************/
ASM(LONG) DMSSFX_GetInfo(REG(a0, struct xadArchiveInfo *ai),
REG(a6, struct xadMasterBase *xadMasterBase))
{
LONG err;
LONG data[3];
if(!(err = xadHookAccess(XADAC_READ, 12, data, ai)))
{
if(!(err = xadHookAccess(XADAC_INPUTSEEK, data[2] == 2 ? 0x537C-12 : 0x58C4-12, 0, ai)))
err = DMS_GetInfo(ai, xadMasterBase);
}
return err;
}
/****************************************************************************/
ASM(BOOL) SDSSFX_RecogData(REG(d0, ULONG size), REG(a0, ULONG *data),
REG(a6, struct xadMasterBase *xadMasterBase))
{
if(*data == HUNK_HEADER)
{
if(data[15] == 0xFDD823C0 && data[17] == 0x2C404EAE &&
data[19] == 0x405A && data[20] == 0x207C0000 && data[21] == 0x020C7600)
return 1;
}
return 0;
}
struct SDSSFXData {
UBYTE Name[20];
ULONG CrSize;
ULONG Size;
UWORD CheckSum;
};
ASM(LONG) SDSSFX_GetInfo(REG(a0, struct xadArchiveInfo *ai),
REG(a6, struct xadMasterBase *xadMasterBase))
{
LONG err, i, j, num = 1;
struct SDSSFXData sd;
struct xadFileInfo *fi = 0, *fi2;
if((err = xadHookAccess(XADAC_INPUTSEEK, 0x41C, 0, ai)))
return err;
while(!err)
{
j = ai->xai_InPos;
if(!(err = xadHookAccess(XADAC_READ, sizeof(struct SDSSFXData), &sd, ai)))
{
if(!(i = strlen(sd.Name)))
break; /* last entry */
if(!(err = xadHookAccess(XADAC_INPUTSEEK, sd.CrSize, 0, ai)))
{
if((fi2 = (struct xadFileInfo *) xadAllocObject(XADOBJ_FILEINFO,
XAD_OBJNAMESIZE, i, TAG_DONE)))
{
fi2->xfi_PrivateInfo = (APTR) j; /* file position */
fi2->xfi_Size = sd.Size;
fi2->xfi_EntryNumber = num++;
fi2->xfi_CrunchSize = sd.CrSize;
fi2->xfi_Flags = XADFIF_NODATE;
for(j = 0; j < i; ++j)
fi2->xfi_FileName[j] = sd.Name[j];
err = xadConvertDates(XAD_DATECURRENTTIME, 1, XAD_GETDATEXADDATE,
&fi2->xfi_Date, TAG_DONE);
if(fi)
fi->xfi_Next = fi2;
else
ai->xai_FileInfo = fi2;
fi = fi2;
}
else
err = XADERR_NOMEMORY;
}
}
}
if(err)
ai->xai_Flags |= XADAIF_FILECORRUPT;
return fi ? 0 : XADERR_ILLEGALDATA;
}
struct DMSDataShort {
ULONG bitbuf;
STRPTR indata;
UBYTE bitcount;
UBYTE DidInit;
UWORD RTV_Medium;
UBYTE Text[32768];
};
ASM(LONG) SDSSFX_UnArchive(REG(a0, struct xadArchiveInfo *ai),
REG(a6, struct xadMasterBase *xadMasterBase))
{
struct ExecBase * SysBase = xadMasterBase->xmb_SysBase;
LONG err;
struct SDSSFXData sd;
if(ai->xai_InPos != (ULONG) ai->xai_CurFile->xfi_PrivateInfo)
{
if((err = xadHookAccess(XADAC_INPUTSEEK, ((ULONG) ai->xai_CurFile->xfi_PrivateInfo) -
ai->xai_InPos, 0, ai)))
return err;
}
if(!(err = xadHookAccess(XADAC_READ, sizeof(struct SDSSFXData), &sd, ai)))
{
struct DMSData *d;
if((d = (struct DMSData *) AllocMem(sizeof(struct DMSDataShort), MEMF_PUBLIC|MEMF_CLEAR)))
{
STRPTR buf;
if((buf = (STRPTR) AllocVec(sd.CrSize, MEMF_PUBLIC)))
{
d->RTV_Medium = 0x3FBE;
if(!(err = xadHookAccess(XADAC_READ, sd.CrSize, buf, ai)))
{
if(!(err = DMSUnpMEDIUM(&buf, sd.Size, d, SysBase)))
{
if(CheckSumDMS(buf, sd.Size) == sd.CheckSum)
err = xadHookAccess(XADAC_WRITE, sd.Size, buf, ai);
else
err = XADERR_CHECKSUM;
}
}
FreeVec(buf);
}
else
err = XADERR_NOMEMORY;
}
else
err = XADERR_NOMEMORY;
}
return err;
}
/****************************************************************************/
struct xadClient SDSSFX_Client = {
NEXTCLIENT, XADCLIENT_VERSION, 1, SDSSFX_VERSION, SDSSFX_REVISION, 100,
XADCF_FILEARCHIVER, XADCID_SDSSFX, "SDS Software SFX",
(BOOL (*)()) SDSSFX_RecogData, (LONG (*)()) SDSSFX_GetInfo, (LONG (*)())
SDSSFX_UnArchive, (void (*)()) DMS_Free};
struct xadClient DMSSFX_Client = {
&SDSSFX_Client, XADCLIENT_VERSION, 1, DMSSFX_VERSION, DMSSFX_REVISION, 100,
XADCF_DISKARCHIVER|XADCF_FILEARCHIVER, XADCID_DMSSFX, "DMS SFX",
(BOOL (*)()) DMSSFX_RecogData, (LONG (*)()) DMSSFX_GetInfo, (LONG (*)())
DMS_UnArchive, (void (*)()) DMS_Free};
struct xadClient DMS_Client = {
&DMSSFX_Client, XADCLIENT_VERSION, 1, DMS_VERSION, DMS_REVISION, sizeof(struct DMSHeader),
XADCF_DISKARCHIVER|XADCF_FILEARCHIVER, XADCID_DMS, "DMS",
(BOOL (*)()) DMS_RecogData, (LONG (*)()) DMS_GetInfo, (LONG (*)())
DMS_UnArchive, (void (*)()) DMS_Free};
#endif /* XADASTER_DMS_C */